Next.js App DirectoryからGeaphQLを利用(apollo client)
共通
apollo clientを用意
code:typescript
import { ApolloClient, InMemoryCache } from "@apollo/client";
const client = new ApolloClient({
uri: "{YOUR_GQL_PATH}",
cache: new InMemoryCache(),
});
export default client;
clientを利用する場合、上記を持ち回す
データ取得(query)
※現状どうがんばってもキャッシュからしかデータを呼んでくれない
公式にはサーバーからclientが呼び出されたら都度clientを作り直せばできるらしい
Fieldsは下記
code:GraphQL Fields
id: Int!
name: String!
desc: String
isDeleted: Boolean!
queryを用意
code:typescript
import { gql } from '@apollo/client';
const GET_USERS = gql`
query users {
users {
name
desc
}
}
`
client.query()をawaitして結果を取得(ついでに型定義)
code:typescript
type User = {
name: string
desc?: string
}
const getUsers = async () => {
const { data } = await client.query<{ users: User[]}>({ query: GET_USERS })
return data.users
}
利用箇所でawait getUsers()から結果を取得すればok
データ更新(mutation) 例はuserの新規作成
mutationを用いるcomponentはClient Componentとする
mutationを用意
code:typescript
import { gql } from '@apollo/client';
const CREATE_USER = gql`
mutation user($user: userCreateInput!) {
create(user: $user) {
name
desc
}
}
`;
userCreateInput fieldsは下記
code:GraphQL Fields
name: String!
desc: String
useMutationからmutation実行用の関数を取得
code:typescript
import { gql, useMutation } from '@apollo/client';
import client from '@/libs/gql_clients';
const create = useMutation(CREATE_USER, { client }); mutation実行用の関数を実行
code:typescript
create({ variables: { user: { name: 'なまえ', desc: '概要' } } })
create()実行時に引数のvariablesにフィールドの各項目を入れてやる
課題
型定義とかうまいことやりたい GQLへの命令か型のどちらかから別の方を自動生成させたい
特にmutation時のvariables指定時にちゃんと型定義からプロパティ名がサジェストされてくれると楽
queryはclientから走らせて、mutationはuseMutationを用いるのがちぐはぐな気がするので、統一できたら嬉しい
ていうか取得はSSR, 更新はCSRでやっているせいでクライアント側が取得したリストのデータをキャッシュに持ってない
更新してQueryの再発行してもサーバー側のキャッシュが更新されない
サーバーサイドでclientを使い回さなければいけるっぽいけど自分の環境ではできなかった
結局GQLの利用箇所を細かく全てuse clientしてやるのが現状一番か?
code:typescript
const UserList = () => {
const { data, loading, error } = useQuery<{users: User[]}>(GET_USERS, { client })
if (loading) {
return <div>読込中</div>
}
return (
<div>
{error && <div>{error.message}</div>}
<ul>
{data && data.users.map((e, i) => <li key={i}>name: {e.name}<br/>desc: {e.desc}</li>)}
</ul>
</div>
)
}